--[[

     Licensed under GNU General Public License v2
      * (c) 2015, Luca CPZ

--]]

local helpers  = require("lain.helpers")
local json     = require("lain.util").dkjson
local focused  = require("awful.screen").focused
local naughty  = require("naughty")
local wibox    = require("wibox")
local math     = math
local os       = os
local string   = string
local type     = type
local tonumber = tonumber

-- qweather 和风天气
-- current weather and X-days forecast
-- lain.widget.qweather

local function factory(args)
    args                        = args or {}

    local weather               = { widget = args.widget or wibox.widget.textbox() }
    local APPID                 = args.APPID -- mandatory
    local timeout               = args.timeout or 60 * 15 -- 15 min
    -- local current_call          = args.current_call  or "curl -s 'https://api.openweathermap.org/data/2.5/weather?id=%s&units=%s&lang=%s&APPID=%s'"
    local current_call          = args.current_call  or "curl -s --compressed 'https://devapi.qweather.com/v7/weather/now?location=%s&lang=%s&gzip=n&key=%s'"
    local forecast_call         = args.forecast_call or "curl -s --compressed 'https://devapi.qweather.com/v7/weather/7d?location=%s&lang=%s&gzip=n&key=%s'"
    local city_id               = args.city_id or 0 -- placeholder
    local units                 = args.units or "m"  -- m is short of metric unit / i is short of imperial unit
    local lang                  = args.lang or "zh"
    -- local cnt                   = args.cnt or 5
    local icons_path            = args.icons_path or helpers.icons_dir .. "qweather_icons/"
    local notification_preset   = args.notification_preset or {}
    local notification_text_fun = args.notification_text_fun or
                                  function (wn)
                                      local day = wn["fxDate"]
                                      local tempMax = math.floor(wn["tempMax"])
                                      local tempMin = math.floor(wn["tempMin"])
                                      local textDay = wn["textDay"]
                                      local textNight = wn["textNight"]
                                      return string.format("<b>%s</b>: %s ~ %s, %d ~ %d°C ", day, textDay, textNight, tempMin, tempMax)
                                  end
    local weather_na_markup     = args.weather_na_markup or " N/A "
    local followtag             = args.followtag or false
    local showpopup             = args.showpopup or "on"
    local settings              = args.settings or function() end
    local weather_uptime        = ""

    weather.icon_path = icons_path .. "na.png"
    weather.icon = wibox.widget.imagebox(weather.icon_path)
    -- weather.widget:set_image(weather_icon_path)
    weather.widget:set_markup(weather_na_markup)

    function weather.show(seconds)
        weather.hide()

        if followtag then
            notification_preset.screen = focused()
        end

        if not weather.notification_text then
            weather.update()
            weather.forecast_update()
        end

        -- io.write(string.format('weather_icon_path: %s', weather.icon_path))
        weather.notification = naughty.notify {
            preset  = notification_preset,
            text    = weather.notification_text,
            icon    = weather.icon_path,
            timeout = type(seconds) == "number" and seconds or notification_preset.timeout
        }
    end

    function weather.hide()
        if weather.notification then
            naughty.destroy(weather.notification)
            weather.notification = nil
        end
    end

    function weather.attach(obj)
        obj:connect_signal("mouse::enter", function()
            weather.show(0)
        end)
        obj:connect_signal("mouse::leave", function()
            weather.hide()
        end)
    end

    function weather.forecast_update()
        local cmd = string.format(forecast_call, city_id, lang, APPID)
        -- io.write(string.format('forecast request cmd: %s', cmd))
        helpers.async(cmd, function(f)
            local err
            weather_now, _, err = json.decode(f, 1, nil)

            if not err and type(weather_now) == "table" and tonumber(weather_now["code"]) == 200 then
                weather.notification_text = ""
                for i = 1, #weather_now["daily"] do

                    weather.notification_text = weather.notification_text ..
                                                notification_text_fun(weather_now["daily"][i]) .. "\n"
                end
                weather.notification_text = weather.notification_text ..
                                                "<b>实时数据：</b>" .. weather_uptime .. "\n"
                weather.notification_text = weather.notification_text ..
                                                "<b>预报数据：</b>" .. weather_now["updateTime"] .. "\n"
            elseif err then
                io.write(string.format("forecast with err: %s\n", tostring(err)))
            else
                io.write(string.format("forecast with no err but something happened! response code: %s\n", tostring(weather_now["code"])))
            end
        end)
    end

    function weather.update()
        local cmd = string.format(current_call, city_id, lang, APPID)
        -- io.write(string.format('now request cmd: %s', cmd))
        helpers.async(cmd, function(f)
            local err
            local weather_now, _, err = json.decode(f, 1, nil)
            -- io.write(string.format('weather_now: %s', tostring(weather_now)))

            if not err and type(weather_now) == "table" and tonumber(weather_now["code"]) == 200 then
                weather_uptime = weather_now["updateTime"]
                local temp = tonumber(weather_now["now"]["temp"])
                local text = weather_now["now"]["text"]:lower()
                local pressure = tonumber(weather_now["now"]["pressure"])
                local wind_dir = weather_now["now"]["windDir"]
                local wind_scale = weather_now["now"]['windScale']
                -- local icon    = weather_now["now"]["icon"]
                icon    = weather_now["now"]["icon"]
                local feels = tonumber(weather_now["now"]["feelsLike"])
                local loc_now = os.time()

                weather_text = string.format("%s %d/%d°C %s%s级", text, temp, feels, wind_dir, wind_scale)

                weather.icon_path = icons_path .. icon .. ".png"
                widget = weather.widget
                settings(weather)
            else
                weather.icon_path = icons_path .. "na.png"
                weather.widget:set_markup(weather_na_markup)
            end

            weather.icon:set_image(weather.icon_path)
        end)
    end

    if showpopup == "on" then weather.attach(weather.widget) end

    weather.timer = helpers.newtimer("weather-" .. city_id, timeout, weather.update, false, true)
    weather.timer_forecast = helpers.newtimer("weather_forecast-" .. city_id, timeout, weather.forecast_update, false, true)

    return weather
end

return factory
